package xyz.xtt.exchange.service.impl;

import static java.util.stream.Collectors.toSet;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.primitives.Longs;

import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.client.response.AssetAllInfoResponse;
import xyz.xtt.exchange.entity.TblUserCollect;
import xyz.xtt.exchange.enums.UserCollectSignTypeEnum;
import xyz.xtt.exchange.mapper.TblUserCollectMapper;
import xyz.xtt.exchange.service.IInnerService;
import xyz.xtt.exchange.service.IUserCollectService;
import xyz.xtt.exchange.vo.NftListVo;
import xyz.xtt.exchange.vo.UserRelationshipVO;
import xyz.xtt.user.client.response.UserInfoResponse;

/**
 * <p>
 * 用户收藏表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-12-28
 */
@Slf4j
@Service
public class UserCollectServiceImpl extends ServiceImpl<TblUserCollectMapper, TblUserCollect> implements IUserCollectService {

	@Autowired
	private IInnerService iInnerService;

	@Override
	public boolean getStatus(Long uid, String signId, int signType) {
		LambdaQueryChainWrapper<TblUserCollect> query = new LambdaQueryChainWrapper<>(baseMapper);
		query.eq(TblUserCollect::getAppUserId, uid).eq(TblUserCollect::getSignId, signId).eq(TblUserCollect::getSignType, signType);
		TblUserCollect tblUserCollect = baseMapper.selectOne(query.getWrapper());
		return tblUserCollect != null;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean add(Long uid, String signId, int signType) {
		TblUserCollect tblUserCollect = new TblUserCollect();
		tblUserCollect.setAppUserId(uid);
		tblUserCollect.setSignId(signId);
		tblUserCollect.setSignType(signType);
		int insert = baseMapper.insert(tblUserCollect);
		return insert > 0;
	}

	@Override
	public boolean del(Long uid, String signId, int signType) {
		LambdaQueryChainWrapper<TblUserCollect> query = new LambdaQueryChainWrapper<>(baseMapper);
		query.eq(TblUserCollect::getAppUserId, uid).eq(TblUserCollect::getSignType, signType).eq(TblUserCollect::getSignId, signId);
		int delete = baseMapper.delete(query.getWrapper());
		return delete > 0;

	}

	@Override
	public List<NftListVo> getCollectList(String uid, Integer currPage, Integer pageSize, int businessType, int orderType) {
		if (businessType >= 0) {
			return new ArrayList<>();
		}
		String page = String.format("limit %d, %d", ((currPage - 1) * pageSize), pageSize);
		MPJLambdaWrapper<TblUserCollect> query = new MPJLambdaWrapper<>();
		query.eq(TblUserCollect::getAppUserId, uid).eq(TblUserCollect::getSignType, UserCollectSignTypeEnum.GOODS.getCode()).selectAll(TblUserCollect.class);
		// .select(TblAsset::getGoodsId, TblAsset::getAssetName,
		// TblAsset::getDescription, TblAsset::getPrice, TblAsset::getUnit,
		// TblAsset::getAmount);

		if (orderType == 0) {
			query.orderByDesc(TblUserCollect::getCreateTime);
		} else {
			query.orderByAsc(TblUserCollect::getCreateTime);
		}
		query.last(page);
		boolean isAsc = orderType == 1;
		query.orderBy(true, isAsc, TblUserCollect::getCreateTime);

		List<TblUserCollect> records = baseMapper.selectList(query);
		List<NftListVo> list = new ArrayList<>();
		Set<String> goodsId = records.stream().map(TblUserCollect::getSignId).collect(toSet());
		if (CollectionUtils.isEmpty(goodsId)) {
			log.info("getCollectList uid:{} isEmpty", uid);
			return list;
		}
		Map<String, AssetAllInfoResponse> batchInfoWithGoodsIdMap = iInnerService.batchInfoGoodsIds(goodsId);
		for (TblUserCollect item : records) {
			String signId = item.getSignId();
			AssetAllInfoResponse assetBaseInfo = batchInfoWithGoodsIdMap.get(signId);
			if (Objects.nonNull(assetBaseInfo)) {
				NftListVo nftListVo = NftListVo
						.builder()
						.goodsId(String.valueOf(signId))
						.assetName(assetBaseInfo.getAsset().getAssetName())
						.description(assetBaseInfo.getAsset().getDescription())
						.price(assetBaseInfo.getAsset().getPrice())
						.unit(assetBaseInfo.getAsset().getUnit())
						.amount(assetBaseInfo.getAsset().getAmount())
						.firstType(assetBaseInfo.getAsset().getFirstType())
						.secondType(assetBaseInfo.getAsset().getSecondType())
						.logoUri(assetBaseInfo.getAssetStatic().getLogoUri())
						.build();
				list.add(nftListVo);
			}
		}
		return list;
	}

	@Override
	public List<UserRelationshipVO> getAllCollect(Long userId, Integer currPage, Integer pageSize) {
		LambdaQueryChainWrapper<TblUserCollect> query = new LambdaQueryChainWrapper<>(baseMapper);
		query.eq(TblUserCollect::getAppUserId, userId);
		query.or().eq(TblUserCollect::getSignId, userId).eq(TblUserCollect::getSignType, UserCollectSignTypeEnum.USER.getCode());
		query.orderByDesc(TblUserCollect::getCreateTime);
		Page<TblUserCollect> page = query.page(new Page<>(currPage, pageSize));
		Page<UserRelationshipVO> result = new Page<>();
		result.setRecords(new ArrayList<>());
		String[] ignoreProperties = { "records" };
		BeanUtils.copyProperties(page, result, ignoreProperties);
		List<TblUserCollect> tblUserCollects = page.getRecords();

		List<Long> myCollectUser = tblUserCollects
				.stream()
				.filter(item -> item.getAppUserId().equals(userId) && UserCollectSignTypeEnum.USER.getCode() == item.getSignType())
				.map(TblUserCollect::getSignId)
				.map(Longs::tryParse)
				.filter(Objects::nonNull)
				.toList();
		if (CollectionUtils.isEmpty(myCollectUser)) {
			return result.getRecords();
		}
		List<Long> collectMe = tblUserCollects.stream().filter(item -> item.getSignId().equals(userId)).map(TblUserCollect::getAppUserId).toList();
		ArrayList<Long> allUserIds = new ArrayList<>();
		allUserIds.addAll(myCollectUser);
		allUserIds.addAll(collectMe);
		Map<Long, UserInfoResponse> allUsers = iInnerService
				.userInfo(allUserIds)
				.stream()
				.collect(Collectors.toMap(UserInfoResponse::getAppUserId, item -> item, (v1, v2) -> v1));
		// 一次性拿到所有用户
//		Map<String, UserVo> allUsers = iTblUserService
//				.getUserInfos(allUserIds)
//				.stream()
//				.collect(Collectors.toMap(UserVo::getUid, item -> item, (v1, v2) -> v1));
		myCollectUser.forEach(id -> {
			UserRelationshipVO vo = new UserRelationshipVO();
			BeanUtils.copyProperties(allUsers.get(id), vo);
			if (collectMe.contains(id)) {
				vo.setCollectType(1);
			}
			result.getRecords().add(vo);
		});
		return result.getRecords();
	}
}
